Este documento tiene la finalidad de describir el primer intento en cuanto a la agrupación y el modelamiento del proyecto final de la materia de analítica predictiva.
La primera tarea que se realizará es el agrupamiento de barrios por estadísticas de accidentes en Medellín en los últimos años. Ya que la idea es ver el comportamiento de la accidentalidad en los barrios en los últimos años, el primer intento será realizado por año y después se verá el promedio para cada barrio.
Para realizar esto cargamos los datos y hacemos un breve análisis descriptivio para ver las variables de interés.
accidentes <- read.csv("D:/jhoparra/2020-1/Predictiva/analitica_predictiva/accidentes3.csv",fileEncoding = "ISO-8859-1")
head(accidentes)
## OBJECTID RADICADO FECHA HORA DIA PERIODO CLASE DIRECCION
## 1 549556 1611786 2018-01-02 03:18:00 2 2018 Atropello CR 64 C CL 103 GG
## 2 549558 1611859 2018-01-02 05:10:00 2 2018 Choque CR 75 CL 59
## 3 549559 1611705 2018-01-02 05:26:00 2 2018 Otro CR 43 A CL 17
## 4 549560 1611750 2018-01-02 05:45:00 2 2018 Choque CR 55 CL 37
## 5 549561 1611719 2018-01-02 06:00:00 2 2018 Otro CR 64 C CL 104
## 6 549562 1611723 2018-01-02 06:30:00 2 2018 Otro CL 65 CR 87
## DIRECCION_ENC CBML TIPO_GEOCOD
## 1 CR 064 C 103 GG 000 00000 0509 Malla vial aproximada: CR 64C-103F
## 2 CR 075 059 000 00000 0703 Malla vial aproximada: CR 76-60
## 3 CR 043 A 017 000 00000 1404 Malla vial
## 4 CR 055 037 000 00000 1011 Malla vial
## 5 CR 064 C 104 000 00000 0502 Malla vial
## 6 CL 065 087 000 00000 0717 Malla vial
## GRAVEDAD BARRIO COMUNA DISENO DIA_NOMBRE MES MES_NOMBRE
## 1 MUERTO Girardot Castilla Tramo de via MARTES 1 enero
## 2 SOLO DAÑOS San Germán Robledo Tramo de via MARTES 1 enero
## 3 HERIDO Castropol El Poblado Lote o Predio MARTES 1 enero
## 4 HERIDO Calle Nueva La Candelaria Tramo de via MARTES 1 enero
## 5 HERIDO Las Brisas Castilla Tramo de via MARTES 1 enero
## 6 HERIDO Robledo Robledo Lote o Predio MARTES 1 enero
## X_MAGNAMED Y_MAGNAMED LONGITUD LATITUD
## 1 835295.9 1188611 -75.56563 6.299676
## 2 832480.2 1185168 -75.59107 6.268543
## 3 834854.0 1179698 -75.56963 6.219092
## 4 834206.8 1182011 -75.57547 6.240001
## 5 835497.3 1188801 -75.56381 6.301392
## 6 831814.6 1186036 -75.59709 6.276391
summary(accidentes)
## OBJECTID RADICADO FECHA HORA
## Min. : 1 Min. :0.000e+00 Length:209438 Length:209438
## 1st Qu.:222812 1st Qu.:1.482e+06 Class :character Class :character
## Median :318870 Median :1.541e+06 Mode :character Mode :character
## Mean :341181 Mean :8.693e+15
## 3rd Qu.:536608 3rd Qu.:1.599e+06
## Max. :686845 Max. :5.002e+20
## DIA PERIODO CLASE DIRECCION
## Min. : 1.00 Min. :2014 Length:209438 Length:209438
## 1st Qu.: 8.00 1st Qu.:2015 Class :character Class :character
## Median :16.00 Median :2016 Mode :character Mode :character
## Mean :15.71 Mean :2016
## 3rd Qu.:23.00 3rd Qu.:2017
## Max. :31.00 Max. :2018
## DIRECCION_ENC CBML TIPO_GEOCOD GRAVEDAD
## Length:209438 Length:209438 Length:209438 Length:209438
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## BARRIO COMUNA DISENO DIA_NOMBRE
## Length:209438 Length:209438 Length:209438 Length:209438
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## MES MES_NOMBRE X_MAGNAMED Y_MAGNAMED
## Min. : 1.000 Length:209438 Min. :820001 Min. :1172269
## 1st Qu.: 4.000 Class :character 1st Qu.:832958 1st Qu.:1181228
## Median : 7.000 Mode :character Median :834286 Median :1183176
## Mean : 6.588 Mean :834059 Mean :1183210
## 3rd Qu.:10.000 3rd Qu.:835344 3rd Qu.:1185499
## Max. :12.000 Max. :845503 Max. :1193451
## LONGITUD LATITUD
## Min. :-75.70 Min. :6.152
## 1st Qu.:-75.59 1st Qu.:6.233
## Median :-75.57 Median :6.251
## Mean :-75.58 Mean :6.251
## 3rd Qu.:-75.57 3rd Qu.:6.272
## Max. :-75.47 Max. :6.343
table(accidentes$GRAVEDAD)
##
## HERIDO MUERTO SOLO DAÑOS
## 114201 1264 93973
table(accidentes$CLASE)
##
## Atropello Caida ocupante Choque
## 6 20679 18578 141447
## Choque y Atropello Incendio Otro Volcamiento
## 1 24 22066 6637
Dado que la clase del accidente puede proveer con estadísticas importantes para realizar el agrupamiento de barrios vamos a unificar para tener categorías con una cantidad importante de registros. Por esta razón los que están en blanco y en incendio serán agregadas a Otro, en tanto que choque y atropello se agregará a los datos de choque.
accidentes <- accidentes %>%
rename(BARRIO_1 = BARRIO)
accidentes$CLASE <- gsub("Incendio","Otro",accidentes$CLASE)
accidentes$CLASE <- gsub("Choque y Atropello","Choque",accidentes$CLASE)
accidentes$CLASE[accidentes$CLASE == ""] <- "Otro"
table(accidentes$CLASE)
##
## Atropello Caida ocupante Choque Otro Volcamiento
## 20679 18578 141448 22096 6637
Con esta información es necesario idear algunos indicadores que más allá de sus valores aporten información y sean útiles para la intervención de la accidentalidad. En un principio se pueden establecer indicadores para cada una de las categorías de la clase de accidente así como la gravedad de los mismos y la población de cada barrio.
Hasta el momento los indicadores definidos para el agrupamiento son:
Se puede evaluar incluir indicadores que relacionen la hora de los accidentes (como variable discretizada) y el clima.
Ya que existen algunos datos faltantes para el tema de los barrios procederemos a asignarle su respectivo barrio de acuerdo a sus coordenadas. Para esto leemos el archivo geoJson que contiene los polígonos de los barrios de Medellín. Este procedimiento es igualmente válido para poder graficar el mapa adecuadamente con los resultados del clustering.
La información de este geojson fue descargada de este portal.
Sys.setlocale(locale = "Spanish")
## [1] "LC_COLLATE=Spanish_Spain.1252;LC_CTYPE=Spanish_Spain.1252;LC_MONETARY=Spanish_Spain.1252;LC_NUMERIC=C;LC_TIME=Spanish_Spain.1252"
barrios_medellin <- readOGR("D:/jhoparra/2020-1/Predictiva/analitica_predictiva/Mapa/Limite_Barrio_Vereda_Catastral.geojson",
stringsAsFactors = FALSE,use_iconv = TRUE,encoding = "UTF-8")
## OGR data source with driver: GeoJSON
## Source: "D:\jhoparra\2020-1\Predictiva\analitica_predictiva\Mapa\Limite_Barrio_Vereda_Catastral.geojson", layer: "Limite_Barrio_Vereda_Catastral"
## with 354 features
## It has 8 fields
head(barrios_medellin@data)
## OBJECTID SHAPEAREA SHAPELEN COMUNA BARRIO CODIGO
## 0 216 156495.4 1853.819 13 08 1308
## 1 217 401784.3 4554.704 70 97 7097
## 2 218 945028.4 5484.487 14 10 1410
## 3 219 190292.6 2801.320 03 10 0310
## 4 220 748198.6 4493.622 60 97 6097
## 5 221 546274.6 3275.185 14 23 1423
## NOMBRE_BARRIO NOMBRE_COMUNA
## 0 San Javier No.2 SAN JAVIER
## 1 Area De Expansion Belen Rincon ALTAVISTA
## 2 Los Naranjos EL POBLADO
## 3 Versalles No. 2 MANRIQUE
## 4 Area de Expansion Altos de Calasanz SAN CRISTOBAL
## 5 Santa María de los Ángeles EL POBLADO
Para realizar este proceso es necesario que los puntos provenientes de la accidentalidad se encuentren en la misma proyección de los polígonos.
accidentes_spatial <- accidentes
coordinates(accidentes_spatial) <- ~LONGITUD+LATITUD
proj4string(accidentes_spatial) <- proj4string(barrios_medellin)
## Warning in proj4string(barrios_medellin): CRS object has comment, which is lost
## in output
Ahora utilizamos la función over de la librería sp para determinar los poligonos en los que se encuentra cada punto, este proceso nos ayudará para dejar los nombres de los barrios estándar para hacer el mapa más adelante.
## Código para determinar en cuáles barrios se encuentran los puntos
contains_barrio <- over(accidentes_spatial, barrios_medellin)
Con esta información ahora añadimos la información del geojson al data frame para poder identificar los puntos que se encuentran sin barrio.
accidentes <- cbind(accidentes,contains_barrio)
head(accidentes)
## OBJECTID RADICADO FECHA HORA DIA PERIODO CLASE DIRECCION
## 1 549556 1611786 2018-01-02 03:18:00 2 2018 Atropello CR 64 C CL 103 GG
## 2 549558 1611859 2018-01-02 05:10:00 2 2018 Choque CR 75 CL 59
## 3 549559 1611705 2018-01-02 05:26:00 2 2018 Otro CR 43 A CL 17
## 4 549560 1611750 2018-01-02 05:45:00 2 2018 Choque CR 55 CL 37
## 5 549561 1611719 2018-01-02 06:00:00 2 2018 Otro CR 64 C CL 104
## 6 549562 1611723 2018-01-02 06:30:00 2 2018 Otro CL 65 CR 87
## DIRECCION_ENC CBML TIPO_GEOCOD
## 1 CR 064 C 103 GG 000 00000 0509 Malla vial aproximada: CR 64C-103F
## 2 CR 075 059 000 00000 0703 Malla vial aproximada: CR 76-60
## 3 CR 043 A 017 000 00000 1404 Malla vial
## 4 CR 055 037 000 00000 1011 Malla vial
## 5 CR 064 C 104 000 00000 0502 Malla vial
## 6 CL 065 087 000 00000 0717 Malla vial
## GRAVEDAD BARRIO_1 COMUNA DISENO DIA_NOMBRE MES MES_NOMBRE
## 1 MUERTO Girardot Castilla Tramo de via MARTES 1 enero
## 2 SOLO DAÑOS San Germán Robledo Tramo de via MARTES 1 enero
## 3 HERIDO Castropol El Poblado Lote o Predio MARTES 1 enero
## 4 HERIDO Calle Nueva La Candelaria Tramo de via MARTES 1 enero
## 5 HERIDO Las Brisas Castilla Tramo de via MARTES 1 enero
## 6 HERIDO Robledo Robledo Lote o Predio MARTES 1 enero
## X_MAGNAMED Y_MAGNAMED LONGITUD LATITUD OBJECTID SHAPEAREA SHAPELEN COMUNA
## 1 835295.9 1188611 -75.56563 6.299676 223 501749.3 3631.300 05
## 2 832480.2 1185168 -75.59107 6.268543 203 429861.9 3759.495 07
## 3 834854.0 1179698 -75.56963 6.219092 335 605804.3 3991.769 14
## 4 834206.8 1182011 -75.57547 6.240001 273 314207.5 2513.434 10
## 5 835497.3 1188801 -75.56381 6.301392 190 350644.3 2596.574 05
## 6 831814.6 1186036 -75.59709 6.276391 229 479641.0 3753.257 07
## BARRIO CODIGO NOMBRE_BARRIO NOMBRE_COMUNA
## 1 09 0509 Girardot CASTILLA
## 2 03 0703 San Germán ROBLEDO
## 3 04 1404 Castropol EL POBLADO
## 4 09 1009 La Alpujarra LA CANDELARIA
## 5 06 0506 Plaza de Ferias CASTILLA
## 6 17 0717 Robledo ROBLEDO
table(is.na(accidentes$NOMBRE_BARRIO))
##
## FALSE TRUE
## 208923 515
Siguen existiendo 515 registros con valores faltantes.
accidentes_na <- accidentes[is.na(accidentes$NOMBRE_BARRIO),]
Viendo los registros y analizándolos podemos ver que estos registros se encuentran por fuera de lo que se considera Medellín de acuerdo a las delimitaciones encontradas en el geojson de la alcaldía, por esta razón se eliminarán del conjunto de datos.
accidentes <- accidentes[!is.na(accidentes$NOMBRE_BARRIO),]
table(is.na(accidentes$NOMBRE_BARRIO))
##
## FALSE
## 208923
Ahora con estos datos podemos proceder a realizar mapas y hacer el análisis por clustering. Para eso vamos a realizar un ejemplo simple con el número total de accidentes.
## Obtener indicador de cantidad de accidentes por barrio en total
barrios_ejemplo <- accidentes %>%
select(NOMBRE_BARRIO) %>%
group_by(NOMBRE_BARRIO) %>%
summarize(conteo = n())
## `summarise()` ungrouping output (override with `.groups` argument)
head(barrios_ejemplo)
## # A tibble: 6 x 2
## NOMBRE_BARRIO conteo
## <chr> <int>
## 1 Aguas Frias 63
## 2 Aldea Pablo VI 36
## 3 Alejandría 428
## 4 Alejandro Echavarría 773
## 5 Alfonso López 1239
## 6 Altamira 720
## Copia del spatial data frame
barrios_med_ejemplo <- barrios_medellin
## Sacar index para organizar luego los registros
barrios_med_ejemplo@data$index <- as.integer(row.names(barrios_med_ejemplo@data))
## Combinar el indicador con el data frame spatial para graficar en mapa
barrios_med_ejemplo@data <- merge(barrios_med_ejemplo@data,barrios_ejemplo,by = "NOMBRE_BARRIO",all.x=TRUE)
barrios_med_ejemplo@data <- barrios_med_ejemplo@data %>% arrange(index)
barrios_med_ejemplo@data$conteo[is.na(barrios_med_ejemplo@data$conteo)] <- 0
Mapa
labels <- sprintf(
"<strong>%s</strong><br/>%g accidentes en total",
barrios_med_ejemplo@data$NOMBRE_BARRIO, barrios_med_ejemplo@data$conteo
) %>% lapply(htmltools::HTML)
pal <- colorNumeric("YlOrRd", NULL)
leaflet(barrios_med_ejemplo)%>%
addTiles() %>%
setView(lat=6.247612, lng=-75.582932, zoom=11.5) %>%
addPolygons(color="grey",weight = 1, fillOpacity = 0.75,opacity = 1, smoothFactor = 0.7, fillColor = ~pal(conteo),
highlight = highlightOptions(
weight = 3,
color = "#666",
fillOpacity = 0.8,
bringToFront = TRUE),
label = labels,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto")) %>%
addLegend(pal = pal, values = ~conteo, opacity = 0.7, title = "Cant. accidentes",
position = "topright")